package com.slipper.http;

import com.slipper.core.cache.CacheUtil;
import com.slipper.core.gson.GsonUtil;
import com.slipper.util.Tool;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;

import java.io.*;
import java.util.Locale;
import java.util.Map;

public class HttpRequestWrapper extends HttpServletRequestWrapper {
    private static final int BUFFER_SIZE = 1024 * 8;
    private final String body;

    public HttpRequestWrapper(HttpServletRequest request, boolean allowedRepeat) throws IOException {
        super(request);

        if (isMultipartContent(request)) {
            this.body = "[文件上传]";
            return;
        }

        BufferedReader bufferedReader = request.getReader();
        StringWriter writer = new StringWriter();
        write(bufferedReader, writer, BUFFER_SIZE);
        String body = writer.getBuffer().toString();
        if (Tool.isBlank(body) && "POST".equalsIgnoreCase(request.getMethod())) {
            throw new RuntimeException("参数不正确！");
        }

        if (body.startsWith("\"")) {
            body = body.substring(1);
        }
        if (body.endsWith("\"")) {
            body = body.substring(0, body.length() - 1);
        }

        if (allowedRepeat) {
            this.body = Tool.isBlank(body) ? "" : body;
            return;
        }

        if (Tool.isNotBlank(body) && body.startsWith("{")) {
            Map<String, Object> dataMap = GsonUtil.toMap(body);
            if (dataMap != null && dataMap.containsKey("_nonce")) {
                String nonce = (String) dataMap.get("_nonce");
                if (CacheUtil.hasKey(nonce)) {
                    throw new RuntimeException("重复提交！");
                } else {
                    CacheUtil.set(nonce, 1, 15 * 60);
                }
            } else {
                throw new RuntimeException("参数不正确！");
            }
        }

        this.body = body;
    }

    public void write(Reader reader, Writer writer, int bufferSize) throws IOException {
        int read;
        char[] buf = new char[bufferSize];
        while ((read = reader.read(buf)) != -1) {
            writer.write(buf, 0, read);
        }
    }

    public boolean isMultipartContent(HttpServletRequest request) {
        if (!"POST".equalsIgnoreCase(request.getMethod())) return false;
        String contentType = request.getContentType();
        return contentType != null && contentType.toLowerCase(Locale.ENGLISH).startsWith("multipart/");
    }

    public String getBody() {
        return body;
    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream inputStream = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {}

            @Override
            public int read() {
                return inputStream.read();
            }
        };
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
}
